package cn.bytepulse.web.admin.service.impl;

import cn.bytepulse.pojo.AjaxResult;
import cn.bytepulse.utils.AssetsUtils;
import cn.bytepulse.utils.MinioUtils;
import cn.bytepulse.utils.RedisUtils;
import cn.bytepulse.web.admin.controller.UserController;
import cn.bytepulse.web.admin.entity.SysAssets;
import cn.bytepulse.web.admin.entity.SysUser;
import cn.bytepulse.web.admin.mapper.SysAssetsMapper;
import cn.bytepulse.web.admin.mapper.SysUserMapper;
import cn.bytepulse.web.admin.service.UserService;
import cn.bytepulse.web.auth.dao.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static cn.bytepulse.utils.ReqUtils.*;

/**
 * @author jiejiebiezheyang
 * @since 2024-03-11 11:00
 */
@Service
@Transactional
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final SysUserMapper sysUserMapper;

    private final RedisUtils redisUtils;

    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    private final SysAssetsMapper sysAssetsMapper;

    private final MinioUtils minioUtils;

    private final AssetsUtils assetsUtils;

    /**
     * 用户权限信息
     */
    @Override
    public Set<String> permissions(Integer userId) {
        Set<String> sysRoles = sysUserMapper.selectUserAllRole(userId);
        boolean hasSuper = sysRoles.contains("super");
        // 用户权限信息
        Set<String> permissions;
        if (hasSuper) {
            // 超级管理员所有权限
            permissions = sysUserMapper.selectAllPermission();
        } else {
            // 其他用户权限
            permissions = sysUserMapper.selectUserAllPermission(userId);
        }
        if (permissions == null || permissions.isEmpty()) {
            permissions = Collections.singleton("none");
        }
        return permissions;
    }

    /**
     * 用户信息
     */
    @Override
    public AjaxResult profiles() throws Exception {
        Integer userId = getUserId();
        SysUser sysUser = sysUserMapper.selectById(userId);
        Map<String, Object> map = new HashMap<>();
        map.put("id", sysUser.getId());
        map.put("username", sysUser.getUsername());
        map.put("nickname", sysUser.getNickname());
        //  刷新 并返回 权限
        Set<String> permissions = permissions(userId);
        LoginUser loginUser = getLoginUser();
        loginUser.setPermissions(permissions);
        long expire = redisUtils.getExpire("login:" + userId, TimeUnit.SECONDS);
        redisUtils.setCacheObject("login:" + userId, loginUser, expire, TimeUnit.SECONDS);
        map.put("permissions", permissions);
        String avatar = "";
        QueryWrapper<SysAssets> wrapper = new QueryWrapper<>();
        wrapper.eq("relation_type", "user_avatar").eq("relation_number", userId);
        SysAssets sysAssets = sysAssetsMapper.selectOne(wrapper);
        if (sysAssets != null) {
            if (minioUtils.fileExists(sysAssets.getObjectKey())) {
                avatar = minioUtils.preSignedUrl(sysAssets.getObjectKey(), 10);
            }
        }
        map.put("avatar", avatar);
        return AjaxResult.success(map);
    }

    /**
     * 上传头像
     *
     * @param file 文件
     */
    @Override
    public AjaxResult avatar(MultipartFile file) throws Exception {
        SysAssets sysAssets = assetsUtils.saveAssets("user_avatar", getUser().getId().toString(), "用户头像", file, true);
        return AjaxResult.success(sysAssets);
    }

    /**
     * 用户信息
     */
    @Override
    public AjaxResult profile() throws Exception {
        String userId = getUser().getId().toString();
        SysUser sysUser = sysUserMapper.selectById(userId);
        sysUser.setPassword(null);
        QueryWrapper<SysAssets> wrapper = new QueryWrapper<>();
        wrapper.eq("relation_type", "user_avatar").eq("relation_number", userId);
        SysAssets sysAssets = sysAssetsMapper.selectOne(wrapper);
        if (sysAssets != null) {
            if (minioUtils.fileExists(sysAssets.getObjectKey())) {
                String avatar = minioUtils.preSignedUrl(sysAssets.getObjectKey(), 10);
                sysUser.setAvatar(avatar);
            }
        }
        return AjaxResult.success(sysUser);
    }

    /**
     * 用户信息更新
     *
     * @param sysUser 用户信息
     */
    @Override
    public AjaxResult profileUpdate(SysUser sysUser) {
        Integer id = getUser().getId();
        SysUser user = new SysUser();
        user.setId(id);
        user.setNickname(sysUser.getNickname());
        user.setEmail(sysUser.getEmail());
        user.setPhone(sysUser.getPhone());
        user.setIntroduction(sysUser.getIntroduction());
        user.setLastUpdate(new Date());
        sysUserMapper.updateById(user);
        return AjaxResult.success(user);
    }

    /**
     * 修改密码
     *
     * @param passwd 密码
     */
    @Override
    public AjaxResult passwd(UserController.Passwd passwd) {
        String oldPassword = passwd.getOldPassword();
        String confirmPassword = passwd.getConfirmPassword();
        String newPassword = passwd.getNewPassword();
        if (!oldPassword.equals(confirmPassword)) {
            return AjaxResult.error("两次密码不一致");
        }
        Integer id = getUser().getId();
        SysUser sysUser = sysUserMapper.selectById(id);
        boolean matches = bCryptPasswordEncoder.matches(oldPassword, sysUser.getPassword());
        if (!matches) {
            return AjaxResult.error("旧密码错误");
        }
        String encode = bCryptPasswordEncoder.encode(newPassword);
        sysUser.setPassword(encode);
        sysUserMapper.updateById(sysUser);
        redisUtils.deleteObject("login:" + id);
        return AjaxResult.success();
    }
}
